package com.pyue.eam.admin.utils;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.convert.Convert;
import cn.hutool.core.date.DatePattern;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.map.MapUtil;
import cn.hutool.core.util.ArrayUtil;
import cn.hutool.core.util.NumberUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.pyue.eam.admin.api.base.BaseDateVo;
import com.pyue.eam.admin.api.base.BaseGraphSearch;
import com.pyue.eam.admin.api.base.BaseSearch;
import com.pyue.eam.admin.api.except.ApiAsserts;
import com.pyue.eam.common.core.util.R;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;

import java.math.BigDecimal;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.*;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.stream.Collectors;

/**
 * @author zhongyuan
 * @Description 常用静态工具类
 * @Date 2020-11-04 18:10
 */
@Slf4j
public class EamUtils {

    /**
     * @param str 被去除的字符 默认去除 _x 去除最后一个数字的字符
     */
    public static String removeLastNumber(String str) {
        return removeLastNumber(str, StrUtil.UNDERLINE);
    }

    /**
     * @param str       被去除的字符
     * @param separator 删除最后一个数字 去除最后一个数字的字符
     */
    public static String removeLastNumber(String str, CharSequence separator) {
        if (StrUtil.isNotBlank(str)) {
            String[] hisTypeBiz = StrUtil.splitToArray(str, separator);

            String lastStr = hisTypeBiz[hisTypeBiz.length - 1];
            if (NumberUtil.isNumber(lastStr)) {
                return ArrayUtil.join(ArrayUtil.remove(hisTypeBiz, hisTypeBiz.length - 1), separator);
            }
        }
        return str;
    }

    /**
     * 默认逗号分割，空字符拼接
     *
     * @param str 需要处理的字符串 去除逗号并排序字符串
     */
    public static String strSortedGoComma(String str) {
        return strSortedGoComma(str, ",", "");
    }

    /**
     * @param str 需要处理的字符串 去除逗号并排序字符串
     */
    public static String strSortedGoComma(String str, String commaStr, String joinStr) {
        if (StrUtil.isBlank(str)) {
            return "";
        }
        return Arrays.stream(str.split(StrUtil.isBlank(commaStr) ? "," : commaStr)).map(StrUtil::trim).sorted().collect(Collectors.joining(StrUtil.isBlank(joinStr) ? "," : joinStr));
    }

    /**
     * 下划线拼接
     */
    public static String underlineSplicing(String param1, String param2) {
        if (StrUtil.isBlank(param1) && StrUtil.isBlank(param2)) {
            return "";
        }
        return param1 + StrUtil.UNDERLINE + param2;
    }

    /**
     * 把list数据放到page里
     */
    public static <T> Page<T> transferPageRecords(Page page, List<T> records) {
        Page<T> result = new Page<>();
        BeanUtils.copyProperties(page, result, "records");
        result.setRecords(records);
        return result;
    }

    /**
     * 给两个long类型,算两个数比例
     */
    public static String percent(long part, long total) {
        if (total <= 0 || part <= 0) {
            return "0";
        }
        if (Convert.toInt(part) * 100 / Convert.toInt(total) >= 100) {
            return "95";
        }
        if (total <= part) {
            return "100";
        }
        return Convert.toInt(part) * 100 / Convert.toInt(total) + "";
    }

    // region 流水号取值
    public static String nextBizDateCode(Integer countNum, Integer countLength) {
        return nextBizDateCode(null, countNum, countLength);
    }

    public static String nextBizDateCode(String codeSuffix, Integer countNum) {
        return nextBizDateCode(codeSuffix, countNum, 2);
    }

    public static String nextBizDateCode(String codeSuffix, Integer countNum, Integer countLength) {
        Integer count = countNum == null ? 0 : countNum;
        LocalDate now = LocalDate.now();
        return StrUtil.concat(false, codeSuffix, Convert.toStr(now.getYear()), Convert.toStr(now.getMonthValue()), Convert.toStr(now.getDayOfMonth()),
                EamUtils.flowCodeSuffixByLength(Convert.toStr(count), countLength));
    }

    /**
     * 支持不同字符串加一 默认十位取后六位加一
     * 根据规则生成流水号
     * 字符串+1方法，该方法将其结尾的整数+1,适用于任何以整数结尾的字符串,不限格式，不限分隔符
     * 取字符串后六位加一
     */
    public static String sixFlowCode(String code) {
        return flowCodeSuffixByLength(code, 6);
    }


    public static String nextCodeSuffix(String code) {
        return nextCodeSuffix(code, StrUtil.EMPTY);
    }

    public static String nextCodeSuffix(String code, String defaultCodeIfNull) {
        if (code == null) {
            return defaultCodeIfNull;
        }
        return flowCodeSuffixByLength(code, code.length());
    }

    /**
     * 支持不同字符串加一
     *
     * @param code   字符串
     * @param length 截取后面位数 所有字符串加一
     */
    public static String flowCodeSuffixByLength(String code, Integer length) {
        if (code == null) {
            return StrUtil.EMPTY;
        }

        // 如果传入的str长度比较小
        int needLength = length - code.length();
        if (needLength > 0) {
            StringBuilder codeBuilder = new StringBuilder(code);
            for (int i = 0; i < needLength; i++) {
                codeBuilder.append('0');
            }
            code = codeBuilder.toString();
        }

        String prefix = code.substring(0, code.length() - length);
        String suffix = code.substring(code.length() - length);
        // 十位数  公司二位  业务两位 流水号六位
        // 根据不是数字的字符拆分字符串
        String[] strs = suffix.split("[^0-9]");
        if (strs.length > 0) {
            // 取出最后一组数字
            String numStr = strs[strs.length - 1];
            // 如果最后一组没有数字(也就是不以数字结尾)，抛NumberFormatException异常
            if (numStr != null && !numStr.isEmpty()) {
                // 取出字符串的长度
                int strLength = numStr.length();
                // 将该数字加一
                String added = String.valueOf(Convert.toLong(numStr) + 1);
                strLength = Math.min(strLength, added.length());
                // 拼接字符串
                return prefix + suffix.subSequence(0, suffix.length() - strLength) + added;
            }
        }
        log.info("传入的参数不是数字");
        // throw new NumberFormatException();
        return Convert.toStr(code) + "1";
    }

    // endregion

    /**
     * 子串是否存在data2集合的元素字符串中
     *
     * @param subStrCommaAble 需要包含在data2的集合
     * @param data2           集合 true存在
     */
    public static Boolean listContainsSublistStr(String subStrCommaAble, List<String> data2) {
        AtomicBoolean atomicBoolean = new AtomicBoolean(false);

        if (!StrUtil.contains(subStrCommaAble, StrUtil.COMMA)) {
            for (Object d2 : data2) {
                if (StrUtil.contains(Convert.toStr(d2), subStrCommaAble)) {
                    atomicBoolean.set(true);
                }
            }
        } else {
            for (String d1 : CollUtil.newArrayList(subStrCommaAble.split(StrUtil.COMMA))) {
                for (Object d2 : data2) {
                    if (StrUtil.contains(Convert.toStr(d2), d1)) {
                        atomicBoolean.set(true);
                    }
                }
            }
        }
        return atomicBoolean.get();
    }

    /**
     * 分割字符串为数字集合
     *
     * @param sourceStr 原字符串 分割后的数字集合
     */
    public static List<Integer> strSplitToIntegerList(String sourceStr) {
        return strSplitToIntegerList(sourceStr, StrUtil.COMMA);
    }

    /**
     * 分割字符串为数字集合
     *
     * @param sourceStr 原字符串
     * @param split     自定义截取字符 分割后的数字集合
     */
    public static List<Integer> strSplitToIntegerList(String sourceStr, CharSequence split) {
        return StrUtil.isNotBlank(sourceStr) ? intArrayToList(StrUtil.splitToInt(sourceStr, split)) : CollUtil.newArrayList();
    }

    public static List<Long> strSplitToLongList(String sourceStr) {
        return StrUtil.isNotBlank(sourceStr) ? longArrayToList(StrUtil.splitToLong(sourceStr, StrUtil.COMMA)) : CollUtil.newArrayList();
    }

    // region 包装工具

    /**
     * 包装图表的时间标识
     *
     * @param baseGraphSearch
     */
    public static <T extends BaseGraphSearch> T wrapperGraphTime(T baseGraphSearch) {
        if (StrUtil.isBlank(baseGraphSearch.getHandleStartTime())
                && StrUtil.isBlank(baseGraphSearch.getHandleEndTime())
                && StrUtil.isNotBlank(baseGraphSearch.getDateFlag())) {

            // 当周
            if ("0".equals(baseGraphSearch.getDateFlag())) {
                baseGraphSearch.setHandleStartTime(DateUtil.format(DateUtil.beginOfDay(DateUtil.offsetDay(DateUtil.date(), -7)),
                        DatePattern.NORM_DATETIME_PATTERN));
            }
            // 当月
            if ("1".equals(baseGraphSearch.getDateFlag())) {
                baseGraphSearch.setHandleStartTime(DateUtil.format(DateUtil.beginOfDay(DateUtil.offsetDay(DateUtil.date(), -30)),
                        DatePattern.NORM_DATETIME_PATTERN));
            }
            // 当季
            if ("2".equals(baseGraphSearch.getDateFlag())) {
                baseGraphSearch.setHandleStartTime(DateUtil.format(DateUtil.beginOfDay(DateUtil.offsetDay(DateUtil.date(), -90)),
                        DatePattern.NORM_DATETIME_PATTERN));
            }
            // 一年
            if ("3".equals(baseGraphSearch.getDateFlag())) {
                baseGraphSearch.setHandleStartTime(DateUtil.format(DateUtil.beginOfDay(DateUtil.offsetDay(DateUtil.date(), -365)),
                        DatePattern.NORM_DATETIME_PATTERN));
            }
            // 三年
            if ("5".equals(baseGraphSearch.getDateFlag())) {
                baseGraphSearch.setHandleStartTime(DateUtil.format(DateUtil.beginOfDay(DateUtil.offsetDay(DateUtil.date(), -1095)),
                        DatePattern.NORM_DATETIME_PATTERN));
            }
            // 五年
            if ("6".equals(baseGraphSearch.getDateFlag())) {
                baseGraphSearch.setHandleStartTime(DateUtil.format(DateUtil.beginOfDay(DateUtil.offsetDay(DateUtil.date(), -1825)),
                        DatePattern.NORM_DATETIME_PATTERN));
            }
            baseGraphSearch.setHandleEndTime(LocalDateTime.now().toString());
        }
        return baseGraphSearch;
    }

    /**
     * 包装台账时间和id
     */
    public static <T extends BaseSearch> T wrapperDateSearch(T search) {
        // 包装年月日表示为 开始结束时间
        if (search.getDateFlag() != null && StrUtil.isBlank(search.getCreateTimeSt()) && StrUtil.isBlank(search.getCreateTimeEt())) {
            // 规则一 年月周
            BaseDateVo baseDateVo = dateWrapBySign(search.getDateFlag());
            search.setCreateTimeSt(baseDateVo.getStTime());
            search.setCreateTimeEt(baseDateVo.getEtTime());
        }

        // 包装ids 到集合 idList
        if (StrUtil.isNotBlank(search.getIds())) {
            List<Long> idList = strSplitToLongList(search.getIds());
            if (CollUtil.isNotEmpty(search.getIdList())) {
                Set<Long> unionDistinct = CollUtil.unionDistinct(search.getIdList(), idList);
                search.setIdList(CollUtil.newArrayList(unionDistinct));
            } else {
                search.setIdList(idList);
            }
        }

        // 包装排除ids 到集合 excludeIdList
        if (StrUtil.isNotBlank(search.getExcludeIds())) {
            List<Long> excludeIdList = strSplitToLongList(search.getExcludeIds());
            if (CollUtil.isNotEmpty(search.getExcludeIdList())) {
                Set<Long> unionDistinct = CollUtil.unionDistinct(search.getExcludeIdList(), excludeIdList);
                search.setExcludeIdList(CollUtil.newArrayList(unionDistinct));
            } else {
                search.setExcludeIdList(excludeIdList);
            }
        }

        // 创建人ids 到集合 idList
        if (StrUtil.isNotBlank(search.getCreateBys())) {
            List<Long> createByList = strSplitToLongList(search.getCreateBys());
            if (CollUtil.isNotEmpty(search.getCreateByList())) {
                Set<Long> unionDistinct = CollUtil.unionDistinct(search.getCreateByList(), createByList);
                search.setCreateByList(CollUtil.newArrayList(unionDistinct));
            } else {
                search.setCreateByList(createByList);
            }
        }

        // 排序
        if (StrUtil.isBlank(search.getOrderFlag()) || !isOrderFlag(search.getOrderFlag())) {
            search.setOrderFlag(null);
        }

        return search;
    }

    public static Boolean isOrderFlag(String orderFlag) {
        if ("desc".equalsIgnoreCase(orderFlag) || "asc".equalsIgnoreCase(orderFlag)) {
            return true;
        }
        return false;
    }

    public static BaseDateVo dateWrapBySign(Integer dataFlag) {
        LocalDate local = LocalDate.now();
        String startDate = "";
        String endDate = "";
        if (dataFlag == 1) {
            // 前端传的 年
            startDate = DateUtil.beginOfYear(EamDateUtil.localDate2Date(local)).toString();
            endDate = DateUtil.endOfYear(EamDateUtil.localDate2Date(local)).toString();
        } else if (dataFlag == 2) {
            // 前端传的 月
            startDate = DateUtil.beginOfMonth(EamDateUtil.localDate2Date(local)).toString();
            endDate = DateUtil.endOfMonth(EamDateUtil.localDate2Date(local)).toString();
        } else if (dataFlag == 3) {
            // 前端传的 周
            startDate = DateUtil.beginOfWeek(EamDateUtil.localDate2Date(local)).toString();
            endDate = DateUtil.endOfWeek(EamDateUtil.localDate2Date(local)).toString();
            // 规则二 前去今明后年
        } else if (dataFlag == 4) {
            // 后年
            LocalDate of = local.plusYears(2);
            startDate = DateUtil.beginOfYear(EamDateUtil.localDate2Date(of)).toString();
            endDate = DateUtil.endOfYear(EamDateUtil.localDate2Date(of)).toString();
        } else if (dataFlag == 5) {
            // 明年
            LocalDate of = local.plusYears(1);
            startDate = DateUtil.beginOfYear(EamDateUtil.localDate2Date(of)).toString();
            endDate = DateUtil.endOfYear(EamDateUtil.localDate2Date(of)).toString();
        } else if (dataFlag == 6) {
            // 前端传的 当年
            startDate = DateUtil.beginOfYear(EamDateUtil.localDate2Date(local)).toString();
            endDate = DateUtil.endOfYear(EamDateUtil.localDate2Date(local)).toString();
        } else if (dataFlag == 7) {
            LocalDate of = local.minusYears(1);
            startDate = DateUtil.beginOfYear(EamDateUtil.localDate2Date(of)).toString();
            endDate = DateUtil.endOfYear(EamDateUtil.localDate2Date(of)).toString();
        } else if (dataFlag == 8) {
            // 前端传的 前年
            LocalDate of = local.minusYears(2);
            startDate = DateUtil.beginOfYear(EamDateUtil.localDate2Date(of)).toString();
            endDate = DateUtil.endOfYear(EamDateUtil.localDate2Date(of)).toString();
            // 规则三 大于2000年
        } else if (dataFlag > 2000) {
            LocalDate of = LocalDate.of(dataFlag, local.getMonth(), local.getDayOfMonth());
            startDate = DateUtil.beginOfYear(EamDateUtil.localDate2Date(of)).toString();
            endDate = DateUtil.endOfYear(EamDateUtil.localDate2Date(of)).toString();
            // 规则四 过去几年内
        } else if (dataFlag <= 0) {
            // 加上一个负数
            LocalDate start = local.plusYears(dataFlag);
            startDate = DateUtil.beginOfYear(EamDateUtil.localDate2Date(start)).toString();
            endDate = DateUtil.endOfYear(EamDateUtil.localDate2Date(local)).toString();
        }
        return BaseDateVo.builder().stTime(startDate).etTime(endDate).build();
    }

    /**
     * 割取真实名称拼接
     *
     * @param userIds         用户id集合,多个用户逗号
     * @param userRealNameMap 所有用户集合 分割后的数字集合
     */
    public static String wrapperUserRealNames(String userIds, Map<Long, String> userRealNameMap) {
        if (StrUtil.isBlank(userIds) || CollUtil.isEmpty(userRealNameMap)) {
            return StrUtil.EMPTY;
        }
        return strSplitToLongList(userIds).stream().filter(Objects::nonNull).map(userRealNameMap::get).filter(StrUtil::isNotBlank).collect(Collectors.joining(StrUtil.COMMA));
    }

    /**
     * 把逗号分割的用户名换成逗号分割的id
     */
    public static String wrapperUserIds(String realNames, Map<String, Long> userRealNameMap) {
        if (StrUtil.isBlank(realNames) || CollUtil.isEmpty(userRealNameMap)) {
            return StrUtil.EMPTY;
        }

        return CollUtil.toList(realNames.split(StrUtil.COMMA)).stream()
                .filter(Objects::nonNull)
                .map(aqe -> Convert.toStr(userRealNameMap.get(aqe)))
                .filter(StrUtil::isNotBlank)
                .collect(Collectors.joining(StrUtil.COMMA));
    }

    // endregion

    // region 数字计算

    /**
     * 把一个数转成负数
     *
     * @param number 数字
     */
    public static Integer numberTransToNegative(Integer number) {
        if (number == null || !NumberUtil.isNumber(number.toString())) {
            return 0;
        }
        return number <= 0 ? number : -Math.abs(number);
    }

    /**
     * 把一个数转成正数
     *
     * @param number 数字
     */
    public static Integer numberTransToAbs(Integer number) {
        if (number == null || !NumberUtil.isNumber(number.toString())) {
            return 0;
        }
        return number >= 0 ? number : Math.abs(number);
    }

    /**
     * 百分比计算
     *
     * @param param1 分子
     * @param param2 分母
     * @return 百分比
     */
    public static Double divCalcPercentage(Integer param1, Integer param2) {
        if (Convert.toInt(param2, 0) == 0 || Convert.toInt(param1, 0) == 0) {
            return 0D;
        }
        param1 = Convert.toInt(param1, 0);
        return NumberUtil.div(BigDecimal.valueOf(param1).multiply(BigDecimal.valueOf(100)), BigDecimal.valueOf(param2), 2).doubleValue();
    }


    /**
     * 百分比计算
     *
     * @param param1 分子
     * @param param2 分母 百分比
     */
    public static Double divCalcPercentage(Double param1, Double param2) {
        if (Convert.toDouble(param2, 0d) == 0d || Convert.toDouble(param1, 0d) == 0d) {
            return 0D;
        }
        return NumberUtil.div(BigDecimal.valueOf(param1).multiply(BigDecimal.valueOf(100)), BigDecimal.valueOf(param2), 2).doubleValue();
    }

    /**
     * 千分比计算
     *
     * @param param1 分子
     * @param param2 分母
     */
    public static Double divCalcPerMille(Double param1, Double param2) {
        if (Convert.toDouble(param2, 0d) == 0d || Convert.toDouble(param1, 0d) == 0d) {
            return 0D;
        }
        return NumberUtil.div(BigDecimal.valueOf(param1).multiply(BigDecimal.valueOf(1000)), BigDecimal.valueOf(param2), 2).doubleValue();
    }

    public static Integer ignoreCase(Map<String, String> map, String str) {
        if (StrUtil.isBlank(str)) {
            return null;
        }
        return Convert.toInt(map.get(str.toLowerCase()));
    }
    // endregion

    /**
     * 忽略大小写获取map的值
     */
    public static String getValueIgnoreKeyCase(Map<String, String> map, String key) {
        if (MapUtil.isEmpty(map) || StrUtil.isBlank(key)) {
            return "";
        }
        return map.entrySet().parallelStream().filter(e -> e.getKey().equalsIgnoreCase(key)).findFirst().map(Map.Entry::getValue).orElse(null);
    }

    /**
     * 人员导入忽略大小写获取map值 转int
     */
    public static Integer getValueIgnoreKeyCaseUser(Map<String, String> map, String key) {
        if (MapUtil.isEmpty(map) || StrUtil.isBlank(key)) {
            return null;
        }
        return Convert.toInt(map.entrySet().parallelStream().filter(e -> e.getKey().equalsIgnoreCase(key)).findFirst().map(Map.Entry::getValue).orElse(null));
    }


    /****************     以下为私有方法  start    ******************/
    private static List<Integer> intArrayToList(int[] intArray) {
        return Arrays.stream(intArray).boxed().collect(Collectors.toList());
    }

    private static List<Long> longArrayToList(long[] longArray) {
        return Arrays.stream(longArray).boxed().collect(Collectors.toList());
    }

    /**
     * 通用的获取远程返回值
     *
     * @param r   远程调用返回值
     * @param <T>
     * @return
     */
    public static <T> T getResData(R<T> r) {
        ApiAsserts.isTrue(r.isOk(), r.getMsg());
        return r.getData();
    }


}
